package naruto.datastructures.graph;

import java.io.*;
import java.util.*;
import naruto.datastructures.instruction.*;

/**
 *
 * @author nacuong
 */
public abstract class Node<T extends Instruction> {
  T instruction;
  Vector<Edge> outcomingEdges;

  public Node(T instruction){
    this.instruction = instruction;
    outcomingEdges = new Vector<Edge>();
  }

  public Node(T instruction, Vector<Edge> outcomingEdges){
    this.instruction = instruction;
    this.outcomingEdges = outcomingEdges;
  }

  public T getInstruction(){
    return this.instruction;
  }

  public void setInstruction(T instruction){
    this.instruction = instruction;
  }

  public Vector<Node> getOutcomingNodes(){
    Vector<Node> nodes = new Vector<Node>();
    for (Edge edge: outcomingEdges)
      nodes.add(edge.target);

    return nodes;
  }

  public Vector<Edge> getOutcomingEdges(){
    return this.outcomingEdges;
  }

  public Edge getOutcomingEdge(Node target){
    for (Edge edge: outcomingEdges)
      if (edge.getTarget().equals(target))
        return edge;

    return null;
  }

  public void addEdge(Edge edge){
    if (edge.getSource().equals(this))
      outcomingEdges.add(edge);
  }

  public boolean contains(Instruction instruction){
    return instruction.equals(this.instruction);
  }

  public boolean contains(Edge edge){
    return outcomingEdges.contains(edge);
  }

  public boolean connectTo(Node node){
    return !(getOutcomingEdge(node) == null);
  }

  @Override
  public boolean equals(Object node){
    return node instanceof Node
            && ((Node)node).getInstruction().equals(instruction);
  }

  /**
   * Dot out the content of this node.
   * The dot file can be visualize using graphviz.
   * @return
   */
  public String toDot(){
    String result = instruction.getInstruction() + " \\n "
            + instruction.getClassName() + " "
            + instruction.getSourceLineNumber()
            + instruction.getSourceCode();
    String location = "";
    for (String i : result.split("\""))
      location += i;
    if (this instanceof IfNode){
      location = "IFNODE " + location;
    }
    return location;
  }

  /**
   * Dot out the outcoming edges of this node.
   * The dot file can be visualize using graphviz.
   * @param out
   */
  public void dotEdges(PrintWriter out) {
    for (int inx = 0; inx < outcomingEdges.size(); inx++){
      String style = null;
      String label = null;
      String color = null;
      String property = "[";
      Edge e = outcomingEdges.get(inx);
      if (e.isAbstract()) style = "dotted";
      if (e.isTrueAttribute()) label = "true";
      if (e.isFalseAttribute()) label = "false";
      if (style != null) property += "style=" + style;
      if (label != null) {
        if (style != null) property += ",";
        property += "label=" + label;
      }
      if (color != null){
        if (style != null || label != null) property += ",";
        property += "color=" + color;
      }
      property += "]";
      if (property.equals("[]")) property = "";

      Node target = e.getTarget();

      out.println("\"" + this.toDot() + "\""
              + " -> " +
              "\"" + target.toDot() + "\" " + property +";");
    }
  }

}
